// Decompiled by Jad v1.5.7g. Copyright 2000 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi 
// Source File Name:   Win32SerialPort.java

package com.sun.comm;

import java.io.*;
import java.util.TooManyListenersException;
import javax.comm.*;

// Referenced classes of package com.sun.comm:
//            NotificationThread, Win32SerialInputStream, Win32SerialOutputStream

class Win32SerialPort extends SerialPort
{

    int nativeHandle;
    private InputStream ins;
    private OutputStream outs;
    private int rcvThreshold;
    int rcvTimeout;
    private boolean framing;
    private int framingByte;
    boolean framingByteReceived;
    private int baudrate;
    private int parity;
    private int dataBits;
    private int stopBits;
    private int flowcontrol;
    private static int speeds[] = {
        75, 110, 134, 150, 300, 600, 1200, 2400, 4800, 9600, 
        19200, 38400, 57600, 0x1c200
    };
    private boolean dtr;
    private boolean rts;
    NotificationThread notificationThread;
    SerialPortEventListener eventListener;
    private int notifyMask;
    static final int NOTIFY_DATA_AVAIL = 1;
    static final int NOTIFY_OUTPUT_EMPTY = 2;
    static final int NOTIFY_RI = 4;
    static final int NOTIFY_CTS = 8;
    static final int NOTIFY_DSR = 16;
    static final int NOTIFY_CD = 32;
    static final int NOTIFY_OE = 64;
    static final int NOTIFY_PE = 128;
    static final int NOTIFY_FE = 256;
    static final int NOTIFY_BI = 512;
    private boolean stateRI;
    private boolean stateCTS;
    private boolean stateDSR;
    private boolean stateCD;
    private boolean stateOE;
    private boolean statePE;
    private boolean stateFE;
    private boolean stateBI;
    Object readSignal;
    private byte wa[];
    private static final int READ_POLL = 200;
    boolean closed;

    Win32SerialPort(String s)
        throws IOException
    {
        rcvThreshold = -1;
        rcvTimeout = -1;
        framing = false;
        dtr = true;
        rts = true;
        closed = false;
        name = s;
        if(!nativeConstructor(s))
        {
            String s1 = "Unable to create port " + s;
            throw new IOException(s1);
        }
        outs = new Win32SerialOutputStream(this);
        ins = new Win32SerialInputStream(this);
        readSignal = new Object();
        wa = new byte[1];
        try
        {
            setFlowControlMode(0);
            setSerialPortParams(9600, 8, 1, 0);
        }
        catch(UnsupportedCommOperationException _ex) { }
        notificationThread = new NotificationThread("Win32SerialPort Notification thread", this);
        notificationThread.start();
    }

    private native boolean nativeConstructor(String s);

    @Override
	public InputStream getInputStream()
        throws IOException
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return ins;
    }

    @Override
	public OutputStream getOutputStream()
        throws IOException
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return outs;
    }

    @Override
	public void enableReceiveThreshold(int i)
        throws UnsupportedCommOperationException
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(i < 0)
        {
            throw new UnsupportedCommOperationException("This threshold value is not supported");
        } else
        {
            rcvThreshold = i;
            return;
        }
    }

    @Override
	public void disableReceiveThreshold()
    {
        if(closed)
        {
            throw new IllegalStateException("Port Closed");
        } else
        {
            rcvThreshold = -1;
            return;
        }
    }

    @Override
	public boolean isReceiveThresholdEnabled()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        return rcvThreshold != -1;
    }

    @Override
	public int getReceiveThreshold()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return rcvThreshold;
    }

    @Override
	public void enableReceiveTimeout(int i)
        throws UnsupportedCommOperationException
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(i < 0)
        {
            throw new UnsupportedCommOperationException("This timeout value is not supported");
        } else
        {
            rcvTimeout = i;
            return;
        }
    }

    @Override
	public void disableReceiveTimeout()
    {
        if(closed)
        {
            throw new IllegalStateException("Port Closed");
        } else
        {
            rcvTimeout = -1;
            return;
        }
    }

    @Override
	public int getReceiveTimeout()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return rcvTimeout;
    }

    @Override
	public boolean isReceiveTimeoutEnabled()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        return rcvTimeout != -1;
    }

    @Override
	public void disableReceiveFraming()
    {
        if(closed)
        {
            throw new IllegalStateException("Port Closed");
        } else
        {
            framing = false;
            nativeDisableFraming();
            return;
        }
    }

    @Override
	public void enableReceiveFraming(int i)
        throws UnsupportedCommOperationException
    {
        if(closed)
        {
            throw new IllegalStateException("Port Closed");
        } else
        {
            framing = true;
            framingByte = i & 0xff;
            nativeEnableFraming(i);
            return;
        }
    }

    @Override
	public int getReceiveFramingByte()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return framingByte;
    }

    @Override
	public boolean isReceiveFramingEnabled()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return framing;
    }

    native void nativeEnableFraming(int i);

    native void nativeDisableFraming();

    @Override
	public void setInputBufferSize(int i)
    {
        if(closed)
        {
            throw new IllegalStateException("Port Closed");
        } else
        {
            nsetInputBufferSize(i);
            return;
        }
    }

    private native void nsetInputBufferSize(int i);

    @Override
	public int getInputBufferSize()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return ngetInputBufferSize();
    }

    private native int ngetInputBufferSize();

    @Override
	public void setOutputBufferSize(int i)
    {
        if(closed)
        {
            throw new IllegalStateException("Port Closed");
        } else
        {
            nsetOutputBufferSize(i);
            return;
        }
    }

    private native void nsetOutputBufferSize(int i);

    @Override
	public int getOutputBufferSize()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return ngetOutputBufferSize();
    }

    private native int ngetOutputBufferSize();

    @Override
	public int getBaudRate()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return baudrate;
    }

    @Override
	public int getDataBits()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return dataBits;
    }

    @Override
	public int getStopBits()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return stopBits;
    }

    @Override
	public int getParity()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return parity;
    }

    @Override
	public void setFlowControlMode(int i)
        throws UnsupportedCommOperationException
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if((i & 0x3) != 0 && (i & 0xc) != 0)
            throw new UnsupportedCommOperationException("Cannot mix hardware and software flow control");
        flowcontrol = i;
        nativeSetFlowcontrolMode(i);
        if((i & 0x1) == 0)
        {
            rts = true;
            dtr = true;
        }
    }

    native void nativeSetFlowcontrolMode(int i);

    @Override
	public int getFlowControlMode()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return flowcontrol;
    }

    @Override
	public void setSerialPortParams(int i, int j, int k, int l)
        throws UnsupportedCommOperationException
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        for(int i1 = 0; i1 < speeds.length; i1++)
        {
            if(i == speeds[i1])
                break;
            if(i < speeds[i1])
                throw new UnsupportedCommOperationException("Unsupported baud rate");
        }

        if(j != 5 && j != 6 && j != 7 && j != 8)
            throw new UnsupportedCommOperationException("Unsupported num of databits");
        if(k != 1 && k != 2 && k != 3)
            throw new UnsupportedCommOperationException("Unsupported num of stopbits");
        if(l != 2 && l != 1 && l != 0)
            throw new UnsupportedCommOperationException("Unsupported parity value");
        baudrate = i;
        parity = l;
        dataBits = j;
        stopBits = k;
        setCommDeviceParams(i, l, j, k);
        saveCommDeviceState();
        try
        {
            setFlowControlMode(flowcontrol);
            return;
        }
        catch(UnsupportedCommOperationException _ex)
        {
            return;
        }
    }

    public native void setCommDeviceParams(int i, int j, int k, int l);

    @Override
	public void sendBreak(int i)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        synchronized(this)
        {
            setCommBreak();
            try
            {
                Thread.sleep(i);
            }
            catch(InterruptedException _ex) { }
            clearCommBreak();
        }
    }

    private native void setCommBreak();

    private native void clearCommBreak();

    @Override
	public void setDTR(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if((flowcontrol & 0x1) == 1)
        {
            return;
        } else
        {
            nativeSetDTR(flag);
            dtr = flag;
            return;
        }
    }

    private native void nativeSetDTR(boolean flag);

    @Override
	public boolean isDTR()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return dtr;
    }

    @Override
	public void setRTS(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if((flowcontrol & 0x1) == 1)
        {
            throw new IllegalStateException("Cannot modify RTS when Hardware flowcontrol is on.");
        } else
        {
            nativeSetRTS(flag);
            rts = flag;
            return;
        }
    }

    private native void nativeSetRTS(boolean flag);

    @Override
	public boolean isRTS()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return rts;
    }

    @Override
	public boolean isCTS()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return nativeIsCTS();
    }

    private native boolean nativeIsCTS();

    @Override
	public boolean isDSR()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return nativeIsDSR();
    }

    private native boolean nativeIsDSR();

    @Override
	public boolean isRI()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return nativeIsRI();
    }

    private native boolean nativeIsRI();

    @Override
	public boolean isCD()
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        else
            return nativeIsCD();
    }

    private native boolean nativeIsCD();

    @Override
	public synchronized void addEventListener(SerialPortEventListener serialporteventlistener)
        throws TooManyListenersException
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(eventListener != null)
            throw new TooManyListenersException();
        eventListener = serialporteventlistener;
        if(eventListener != null && notificationThread == null)
        {
            notificationThread = new NotificationThread("Win32SerialPort Notification thread", this);
            notificationThread.start();
        }
    }

    @Override
	public synchronized void removeEventListener()
    {
        if(closed)
        {
            throw new IllegalStateException("Port Closed");
        } else
        {
            eventListener = null;
            return;
        }
    }

    @Override
	public synchronized void notifyOnDataAvailable(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x1;
        else
            notifyMask &= 0xfffffffe;
        nnotifyOnDataAvailable(flag);
    }

    private native void nnotifyOnDataAvailable(boolean flag);

    @Override
	public synchronized void notifyOnOutputEmpty(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x2;
        else
            notifyMask &= 0xfffffffd;
        nnotifyOnOutputEmpty(flag);
    }

    private native void nnotifyOnOutputEmpty(boolean flag);

    @Override
	public synchronized void notifyOnCTS(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x8;
        else
            notifyMask &= 0xfffffff7;
        nnotifyOnCTS(flag);
    }

    private native void nnotifyOnCTS(boolean flag);

    @Override
	public synchronized void notifyOnDSR(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x10;
        else
            notifyMask &= 0xffffffef;
        nnotifyOnDSR(flag);
    }

    private native void nnotifyOnDSR(boolean flag);

    @Override
	public synchronized void notifyOnCarrierDetect(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x20;
        else
            notifyMask &= 0xffffffdf;
        nnotifyOnCarrierDetect(flag);
    }

    private native void nnotifyOnCarrierDetect(boolean flag);

    @Override
	public synchronized void notifyOnRingIndicator(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x4;
        else
            notifyMask &= 0xfffffffb;
        nnotifyOnRingIndicator(flag);
    }

    private native void nnotifyOnRingIndicator(boolean flag);

    @Override
	public synchronized void notifyOnOverrunError(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x40;
        else
            notifyMask &= 0xffffffbf;
        nnotifyOnOverrunError(flag);
    }

    private native void nnotifyOnOverrunError(boolean flag);

    @Override
	public synchronized void notifyOnParityError(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x80;
        else
            notifyMask &= 0xffffff7f;
        nnotifyOnParityError(flag);
    }

    private native void nnotifyOnParityError(boolean flag);

    @Override
	public synchronized void notifyOnFramingError(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x100;
        else
            notifyMask &= 0xfffffeff;
        nnotifyOnFramingError(flag);
    }

    private native void nnotifyOnFramingError(boolean flag);

    @Override
	public synchronized void notifyOnBreakInterrupt(boolean flag)
    {
        if(closed)
            throw new IllegalStateException("Port Closed");
        if(flag)
            notifyMask |= 0x200;
        else
            notifyMask &= 0xfffffdff;
        nnotifyOnBreakInterrupt(flag);
    }

    private native void nnotifyOnBreakInterrupt(boolean flag);

    native int waitForEvent();

    private void saveCommDeviceState()
    {
        stateRI = isRI();
        stateCTS = isCTS();
        stateDSR = isDSR();
        stateCD = isCD();
    }

    void sendCTSevent()
    {
        if((notifyMask & 0x8) == 8)
        {
            boolean flag = isCTS();
            if(flag != stateCTS)
            {
                SerialPortEvent serialportevent = new SerialPortEvent(this, 3, stateCTS, flag);
                eventListener.serialEvent(serialportevent);
                stateCTS = flag;
            }
        }
    }

    void sendDSRevent()
    {
        if((notifyMask & 0x10) == 16)
        {
            boolean flag = isDSR();
            if(flag != stateDSR)
            {
                SerialPortEvent serialportevent = new SerialPortEvent(this, 4, stateDSR, flag);
                eventListener.serialEvent(serialportevent);
                stateDSR = flag;
            }
        }
    }

    void sendCDevent()
    {
        if((notifyMask & 0x20) == 32)
        {
            boolean flag = isCD();
            if(flag != stateCD)
            {
                SerialPortEvent serialportevent = new SerialPortEvent(this, 6, stateCD, flag);
                eventListener.serialEvent(serialportevent);
                stateCD = flag;
            }
        }
    }

    void sendRIevent()
    {
        if((notifyMask & 0x4) == 4)
        {
            boolean flag = isRI();
            if(flag != stateRI)
            {
                SerialPortEvent serialportevent = new SerialPortEvent(this, 5, stateRI, flag);
                eventListener.serialEvent(serialportevent);
                stateRI = flag;
            }
        }
    }

    void sendBIevent()
    {
        if((notifyMask & 0x200) == 512)
        {
            SerialPortEvent serialportevent = new SerialPortEvent(this, 10, false, true);
            eventListener.serialEvent(serialportevent);
        }
    }

    void sendOEevent()
    {
        if((notifyMask & 0x40) == 64)
        {
            SerialPortEvent serialportevent = new SerialPortEvent(this, 7, false, true);
            eventListener.serialEvent(serialportevent);
        }
    }

    void sendPEevent()
    {
        if((notifyMask & 0x80) == 128)
        {
            SerialPortEvent serialportevent = new SerialPortEvent(this, 8, false, true);
            eventListener.serialEvent(serialportevent);
        }
    }

    void sendFEevent()
    {
        if((notifyMask & 0x100) == 256)
        {
            SerialPortEvent serialportevent = new SerialPortEvent(this, 9, false, true);
            eventListener.serialEvent(serialportevent);
        }
    }

    void sendOutputEmptyEvent()
    {
        if((notifyMask & 0x2) == 2)
        {
            SerialPortEvent serialportevent = new SerialPortEvent(this, 2, false, true);
            eventListener.serialEvent(serialportevent);
        }
    }

    void sendDataAvailEvent()
    {
        if((notifyMask & 0x1) == 1)
        {
            SerialPortEvent serialportevent = new SerialPortEvent(this, 1, false, true);
            eventListener.serialEvent(serialportevent);
        }
    }

    @Override
	protected void finalize()
        throws Throwable
    {
        nativeFinalize();
    }

    private native void nativeFinalize();

    void write(int i)
        throws IOException
    {
        wa[0] = (byte)i;
        write(wa, 0, 1);
    }

    void write(byte abyte0[], int i, int j)
        throws IOException
    {
        for(int k = 0; k < j;)
        {
            int l = nwrite(abyte0, i + k, j - k <= 512 ? j - k : 512);
            if(l > 0)
                k += l;
            else
                throw new IOException("write error");
        }

    }

    private native int nwrite(byte abyte0[], int i, int j);

    private native int nread(byte abyte0[], int i, int j)
        throws IOException;

    native int available()
        throws IOException;

    int read()
        throws IOException
    {
        byte abyte0[] = new byte[1];
        switch(read(abyte0, 0, 1))
        {
        case 1: // '\001'
            return abyte0[0] & 0xff;
        }
        return -1;
    }

    int read(byte abyte0[], int i, int j)
        throws IOException
    {
        int k = 200;
        int l = 0;
        if(rcvTimeout == 0)
            l = 0;
        else
        if(rcvTimeout == -1)
        {
            l = 0;
        } else
        {
            k = rcvTimeout >= 200 ? 200 : rcvTimeout;
            l = rcvTimeout / k;
        }
        int i1 = 0;
        int j1 = 0;
        while(i1 < j) 
        {
            int k1 = available();
            if(k1 > 0)
            {
                int l1 = nread(abyte0, i + i1, j - i1);
                if(l1 >= 0)
                    i1 += l1;
                else
                    return i1;
            }
            if(rcvTimeout == 0)
                return i1;
            if(i1 == j)
                return i1;
            if(framing && framingByteReceived)
            {
                framingByteReceived = false;
                return i1;
            }
            if(rcvTimeout == -1)
            {
                if(rcvThreshold == -1)
                {
                    if(i1 > 0)
                        return i1;
                } else
                if(i1 >= Math.min(rcvThreshold, j))
                    return i1;
            } else
            {
                if(j1 >= l)
                    return i1;
                if(rcvThreshold == -1)
                {
                    if(i1 > 0)
                        return i1;
                } else
                if(i1 >= Math.min(rcvThreshold, j))
                    return i1;
            }
            synchronized(readSignal)
            {
                j1++;
                try
                {
                    readSignal.wait(k);
                }
                catch(InterruptedException _ex)
                {
                    byte byte0 = -1;
                    return byte0;
                }
            }
        }
        return i1;
    }

    @Override
	public void close()
    {
        eventListener = null;
        nativeFinalize();
        nativeHandle = 0;
        closed = true;
        super.close();
    }

}
